package com.ruoyi.system.service.impl;

import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.Method;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.Ztree;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.service.ISysConfigService;

/**
 * 参数配置 服务层实现
 *
 * @author ruoyi
 */
@Service
public class SysConfigServiceImpl implements ISysConfigService
{
    @Autowired
    private SysConfigMapper configMapper;

    @Value("${version}")
    private String version;

    /**
     * 项目启动时，初始化参数到缓存
     */
    @PostConstruct
    public void init()
    {
        loadingConfigCache();
    }

    /**
     * 查询参数配置信息
     *
     * @param configId 参数配置ID
     * @return 参数配置信息
     */
    @Override
    public SysConfig selectConfigById(Long configId)
    {
        SysConfig config = new SysConfig();
        config.setConfigId(configId);
        return configMapper.selectConfig(config);
    }

    /**
     * 根据键名查询参数配置信息
     *
     * @param configKey 参数key
     * @return 参数键值
     */
    @Override
    public String selectConfigByKey(String configKey)
    {
        String configValue = Convert.toStr(CacheUtils.get(getCacheName(), getCacheKey(configKey)));
        if (StringUtils.isNotEmpty(configValue))
        {
            return configValue;
        }
        SysConfig config = new SysConfig();
        config.setConfigKey(configKey);
        SysConfig retConfig = configMapper.selectConfig(config);
        if (StringUtils.isNotNull(retConfig))
        {
            if(StringUtils.equals(configKey, "platform.domain")&&StringUtils.isBlank(retConfig.getConfigValue())){
                return "autohttps.cn";
            }
            if(StringUtils.equals(configKey, "system.name")&&StringUtils.isBlank(retConfig.getConfigValue())){
                return "AUTOHTTPS";
            }
            CacheUtils.put(getCacheName(), getCacheKey(configKey), retConfig.getConfigValue());
            return retConfig.getConfigValue();
        }
        if(StringUtils.equals(configKey, "platform.domain")){
            return "autohttps.cn";
        }
        if(StringUtils.equals(configKey, "system.name")){
            return "AUTOHTTPS";
        }
        return StringUtils.EMPTY;
    }


    public void syncPlatform(){
        try {
            HttpRequest request = HttpRequest.get(CommUtils.REQ_API_URI+"/SSL/api/v1/setPlatformInfo");
            //先封装参数得到签名值
            JSONObject paramObj = new JSONObject();
            paramObj.set("platformVersion", version);
            paramObj.set("platformDomain", selectConfigByKey("platform.domain"));
            paramObj.set("alyKeyId", selectConfigByKey("aly.AccessKeyID"));
            paramObj.set("alyKeySecret", selectConfigByKey("aly.AccessKeySecret"));
            //得到签名
            String sign = SignUtils.createSign(paramObj, selectConfigByKey("api.appSecret"));
            //赋值必要请求头的值
            request.header("Referer", selectConfigByKey("self.domain"));
            request.header("ssl-sign", sign);   //签名字符串
            request.header("ssl-appid", selectConfigByKey("api.appId"));  //appid
            request.header("ssl-timestamp", String.valueOf(DateUtil.current()));    // 当前时间戳
            //把请求参数赋值到请求中
            request.body(JSONUtil.toJsonStr(paramObj));
            //发起请求
            HttpResponse response = request.execute();
            if(response.getStatus() == 200){
                JSONObject resObj = JSONUtil.parseObj(response.body());
                if(resObj.getInt("code") == 0){
                    Console.log("同步平台信息成功！");
                }else{
                    Console.log("同步平台信息失败！");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            Console.log("同步平台信息失败："+e.getMessage());
        }
    }

    /**
     * 查询参数配置列表
     *
     * @param config 参数配置信息
     * @return 参数配置集合
     */
    @Override
    public List<SysConfig> selectConfigList(SysConfig config)
    {
        return configMapper.selectConfigList(config);
    }

    /**
     * 新增参数配置
     *
     * @param config 参数配置信息
     * @return 结果
     */
    @Override
    public int insertConfig(SysConfig config)
    {
        int row = configMapper.insertConfig(config);
        if (row > 0)
        {
            CacheUtils.put(getCacheName(), getCacheKey(config.getConfigKey()), config.getConfigValue());
        }
        return row;
    }

    /**
     * 修改参数配置
     *
     * @param config 参数配置信息
     * @return 结果
     */
    @Override
    public int updateConfig(SysConfig config)
    {
        SysConfig temp = configMapper.selectConfigById(config.getConfigId());
        if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey()))
        {
            CacheUtils.remove(getCacheName(), getCacheKey(temp.getConfigKey()));
        }

        int row = configMapper.updateConfig(config);
        if (row > 0)
        {
            CacheUtils.put(getCacheName(), getCacheKey(config.getConfigKey()), config.getConfigValue());
        }
        return row;
    }

    /**
     * 批量删除参数配置对象
     *
     * @param ids 需要删除的数据ID
     */
    @Override
    public void deleteConfigByIds(String ids)
    {
        Long[] configIds = Convert.toLongArray(ids);
        for (Long configId : configIds)
        {
            SysConfig config = selectConfigById(configId);
            if (StringUtils.equals(UserConstants.YES, config.getConfigType()))
            {
                throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
            }
            configMapper.deleteConfigById(configId);
            CacheUtils.remove(getCacheName(), getCacheKey(config.getConfigKey()));
        }
    }

    /**
     * 加载参数缓存数据
     */
    @Override
    public void loadingConfigCache()
    {
        List<SysConfig> configsList = configMapper.selectConfigList(new SysConfig());
        for (SysConfig config : configsList)
        {
            CacheUtils.put(getCacheName(), getCacheKey(config.getConfigKey()), config.getConfigValue());
        }
    }

    /**
     * 清空参数缓存数据
     */
    @Override
    public void clearConfigCache()
    {
        CacheUtils.removeAll(getCacheName());
    }

    /**
     * 重置参数缓存数据
     */
    @Override
    public void resetConfigCache()
    {
        clearConfigCache();
        loadingConfigCache();
    }

    /**
     * 校验参数键名是否唯一
     *
     * @param config 参数配置信息
     * @return 结果
     */
    @Override
    public boolean checkConfigKeyUnique(SysConfig config)
    {
        Long configId = StringUtils.isNull(config.getConfigId()) ? -1L : config.getConfigId();
        SysConfig info = configMapper.checkConfigKeyUnique(config.getConfigKey());
        if (StringUtils.isNotNull(info) && info.getConfigId().longValue() != configId.longValue())
        {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 获取cache name
     *
     * @return 缓存名
     */
    private String getCacheName()
    {
        return Constants.SYS_CONFIG_CACHE;
    }

    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    private String getCacheKey(String configKey)
    {
        return Constants.SYS_CONFIG_KEY + configKey;
    }

    public List<Ztree> selectTree(){
        List<SysDictData> dictDataList = DictUtils.getDictCache("config_param_type");
        return initZtree(dictDataList);
    }

    /**
     * 对象转部门树
     *
     * @param dictDataList 服务器列表
     * @return 树结构列表
     */
    public List<Ztree> initZtree(List<SysDictData> dictDataList)
    {
        List<Ztree> ztrees = new ArrayList<Ztree>();
        for (SysDictData dictData : dictDataList)
        {
            if (UserConstants.DEPT_NORMAL.equals(dictData.getStatus()))
            {
                Ztree ztree = new Ztree();
                ztree.setId(dictData.getDictCode());
                ztree.setpId(0L);
                ztree.setName(dictData.getDictLabel());
                ztree.setTitle(dictData.getDictValue());
                ztrees.add(ztree);
            }
        }
        return ztrees;
    }

    /**
     * 通过appId获取平台
     * @param appId 1
     * @param appSecret 1
     */
    public AjaxResult getPlatformInfoByAppId(String reqUri, String appId, String appSecret){
        try {
            HttpRequest request = new HttpRequest(reqUri+"/SSL/api/v1/get_platform_info");
            request.method(Method.POST);
            //先封装参数得到签名值
            JSONObject paramObj = new JSONObject();
            paramObj.set("appId", appId);
            //得到签名
            String sign = SignUtils.createSign(paramObj, appSecret);
            //赋值必要请求头的值
            request.header("Referer", selectConfigByKey("self.domain"));
            request.header("ssl-sign", sign);   //签名字符串
            request.header("ssl-appid", appId);  //appid
            request.header("ssl-timestamp", String.valueOf(DateUtil.current()));    // 当前时间戳
            //把请求参数赋值到请求中
            request.body(JSONUtil.toJsonStr(paramObj));
            //发起请求
            HttpResponse response = request.execute();
            if(response.getStatus() == 200){
                JSONObject resobjObj = JSONUtil.parseObj(response.body());
                if(resobjObj.getInt("code") == 0){
                    return AjaxResult.success("获取成功",resobjObj.getStr("data"));
                }
                return AjaxResult.error(resobjObj.getStr("msg"));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return AjaxResult.error("未知错误！");
    }
}
